package com.pachong.android.frameworkbase.utils;

import android.util.Log;

import java.util.HashSet;
import java.util.Set;

/**
 * switch log 日志打印工具
 *
 * Created by Zoi.
 * E-mail：KyluZoi@gmail.com
 * 2016/10/20
 *
 * update data: 2016-10-25  by pengveivei@sina.cn
 *
 * 功能点：
 * 1. 可追踪日志位置
 * 2. 可配置需要过滤的tag（可以通过hide方法，也可以在下面的static 块中配置）
 * 3. 控制log显示的全局开关
 * 4. 可以配置缺省的tag，打log不用输入tag，方便个人开发调试
 * 5. 使用方法和android.Log 一致，无学习成本
 *
 */

public final class SLog {
	private static boolean sEnable = false;  //Switch is enable

	/**
	 * 默认的tag
	 */
	private static String sDefaultTag = "default_tag"; // 默认的tag

	public static void init(boolean enable, String defaultTag, String... tagsForHide) {
		sEnable = enable;
		sDefaultTag = defaultTag;
		if (tagsForHide != null) {
			for (String tagForHide : tagsForHide) {
				mHideTagSet.add(tagForHide);
			}
		}
	}

	/**
	 * 过滤器，保存不打出log的TAG
	 */
	private final static Set<String> mHideTagSet = new HashSet<>();

	static {
		sEnable = true;

		//默认的tag
		sDefaultTag = "default_tag_xxx";

		// 配置需要隐藏的lgo
		hide("zhao_tag");
	}

	/**
	 * 隐藏某类tag
	 *
	 * @param tag
	 */
	public static void hide(String tag) {
		mHideTagSet.add(tag);
	}


	/**
	 * 初始化log的配置  可在application中配置  否则使用默认
	 *
	 * @param enable
	 */
	public static void enable(boolean enable) {
		sEnable = enable;

	}

	/**
	 * 打印 error 日志
	 *
	 * @param tag
	 * @param msg
	 * @param params
	 */
	public static void e(String tag, String msg, Object... params) {
		if (shouldLogOut(tag)) {
			if (params != null && params.length > 0) {
				Log.e(tag, String.format(msg, params) + getLogInWhere());
			} else {
				Log.e(tag, msg + getLogInWhere());
			}
		}
	}

	public static void e(String msg) {
		e(sDefaultTag, msg);
	}

	/**
	 * debug日志
	 *
	 * @param tag
	 * @param msg
	 * @param params
	 */
	public static void d(String tag, String msg, Object... params) {
		if (shouldLogOut(tag)) {
			if (params != null && params.length > 0) {
				Log.d(tag, String.format(msg, params) + getLogInWhere());
			} else {
				Log.d(tag, msg + getLogInWhere());
			}
		}
	}

	public static void d(String msg) {
		d(sDefaultTag, msg);
	}

	/**
	 * warn 日志
	 * @param tag
	 * @param msg
	 * @param params
	 */
	public static void w(String tag, String msg, Object... params) {
		if (shouldLogOut(tag)) {
			if (params != null && params.length > 0) {
				Log.w(tag, String.format(msg, params) + getLogInWhere());
			} else {
				Log.w(tag, msg + getLogInWhere());
			}
		}
	}

	public static void w(String msg) {
		w(sDefaultTag, msg);
	}

	/**
	 * info日志
	 * @param tag
	 * @param msg
	 * @param params
	 */
	public static void i(String tag, String msg, Object... params) {
		if (shouldLogOut(tag)) {
			if (params != null && params.length > 0) {
				Log.i(tag, String.format(msg, params) + getLogInWhere());
			} else {
				Log.i(tag, msg + getLogInWhere());
			}
		}
	}

	public static void i(String msg) {
		i(sDefaultTag, msg);
	}

	/**
	 * verbose日志
	 * @param tag
	 * @param msg
	 * @param params
	 */
	public static void v(String tag, String msg, Object... params) {
		if (shouldLogOut(tag)) {
			if (params != null && params.length > 0) {
				Log.v(tag, String.format(msg, params) + getLogInWhere());
			} else {
				Log.v(tag, msg + getLogInWhere());
			}
		}
	}

	public static void v(String msg) {
		v(sDefaultTag, msg);
	}


	/**
	 * 判断所传的tag是否符合打印的条件
	 *
	 * @param tag
	 * @return
	 */
	private static boolean shouldLogOut(String tag) {
		// disable
		if (!sEnable) {
			return false;
		}

		// tag被User设置成隐藏了
		if (mHideTagSet.contains(tag)) {
			return false;
		}

		// 可以打印
		return true;
	}


	/**
	 * 获得 Log 栈
	 *
	 * @return
	 */
	private static String getLogString() {
		StringBuffer err = new StringBuffer();
		StackTraceElement[] stack = Thread.currentThread().getStackTrace();
		for (int i = 0; i < stack.length; i++) {
			err.append("\tat ");
			err.append(stack[i].toString());
			err.append("\n");
		}
		return err.toString();
	}

	/**
	 * 获取日志打印位置
	 *
	 * @return
	 */
	private static String getLogInWhere() {
		// find the target invoked method
		StackTraceElement targetStackTrace = null;
		boolean shouldTrace = false;
		StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
		for (StackTraceElement stackTraceElement : stackTrace) {
			boolean isLogMethod = stackTraceElement.getClassName().equals(SLog.class.getName());
			if (shouldTrace && !isLogMethod) {
				targetStackTrace = stackTraceElement;
				break;
			}
			shouldTrace = isLogMethod;
		}
		String logPlace = "\t" + "(" + targetStackTrace.getFileName() + ":"
				+ targetStackTrace.getLineNumber() + ")";//打印日志位置
		return logPlace;
	}


	public void test() {
		// Should config in Application
//		SLog.init(true, "my_tag", "vivi_tag");
		SLog.e("default");
		SLog.e("vivi_tag", "vivi message");
		SLog.e("hukai_tag", "hukai message");
		SLog.e("zhao_tag", "zhao message");
		SLog.e("haha", "default");

		SLog.hide("vivi_tag");
		SLog.i("default");
		SLog.i("vivi_tag", "vivi message");
		SLog.i("hukai_tag", "hukai message");
		SLog.i("zhao_tag", "zhao message");
		SLog.i("haha", "default");


	}

}
